import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger } from '@nestjs/common';
import { Request, Response } from 'express';
import { LoggingService } from '@/services/logging.service';
import { getCurrentContext } from '@/common/async-context';
import { ResponseUtil } from '@/common/utils/response.util';

@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
    private readonly logger = new Logger(GlobalExceptionFilter.name);

    constructor(private readonly loggingService: LoggingService) {}

    catch(exception: unknown, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const response = ctx.getResponse<Response>();
        const request = ctx.getRequest<Request>();

        // 获取异常信息
        let status = HttpStatus.INTERNAL_SERVER_ERROR;
        let message = '内部服务器错误';
        let error = 'Internal Server Error';

        if (exception instanceof HttpException) {
            status = exception.getStatus();
            const exceptionResponse = exception.getResponse();

            if (typeof exceptionResponse === 'object' && exceptionResponse !== null) {
                message = (exceptionResponse as any).message || exception.message;
                error = (exceptionResponse as any).error || exception.message;
            } else {
                message = exception.message;
                error = exception.message;
            }
        } else if (exception instanceof Error) {
            message = exception.message;
            error = exception.name;
        }

        // 从 AsyncLocalStorage 获取上下文
        const context = getCurrentContext();

        // 记录错误日志
        this.loggingService.error('全局异常过滤器捕获到异常', exception as Error, {
            traceId: context?.traceId || 'unknown',
            uri: context?.uri || request.url,
            method: request.method,
            statusCode: status,
            message,
            error,
        });

        // 构建标准错误响应
        const errorResponse = ResponseUtil.error(message, status, error, {
            path: request.url,
            method: request.method,
            statusCode: status,
        });

        // 发送错误响应
        response.status(status).json(errorResponse);
    }
}
